﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Web;
using MyHelpers;
using NPOI.XWPF.UserModel;

namespace DailyReport.Helpers
{
    public static class DrDocxHelper
    {
        /// <summary>周序号，从1开始</summary>
        private static int indexWeek = 1;

        public static List<ProjectDetail> GetProjectList(DataTable dt, DateTime startDate, DateTime endDate)
        {
            var dic = new Dictionary<string, ProjectDetail>();
            foreach (DataRow dr in dt.Rows)
            {
                DateTime recDate = Convert.ToDateTime(dr["记录时间"]);
                if (recDate > endDate || recDate < startDate) continue;

                string projectName = dr["项目"].ToString();
                if (string.IsNullOrEmpty(projectName)) continue;
                if (!dic.ContainsKey(projectName))
                    dic.Add(projectName, new ProjectDetail(projectName));
                double workHour = Convert.ToDouble(dr["工作量"]);
                double overtime = Convert.ToDouble(dr["加班量"]);
                string text = dr["工作描述"].ToString();
                string remark = dr["备注"].ToString();
                var detail = dic[projectName];
                detail.WorkHour += workHour;
                detail.Overtime += overtime;
                detail.TextList.Add(text);
                detail.RemarkList.Add(remark);
            }
            return dic.Values.ToList();
        }

        public static bool WriteDocxWeek(ref XWPFDocument doc, DataTable dt, DateTime startDate,
            DateTime endDate, bool summarize = false)
        {
            // 插入分页符
            if (indexWeek!=1)
            {
                XWPFParagraph pBreak = doc.CreateParagraph();
                XWPFRun rBreak = pBreak.CreateRun();
                rBreak.AddBreak();
            }
            // 获取数据
            List<ProjectDetail> list = GetProjectList(dt, startDate, endDate);
            int count = list.Count;
            // 标题
            XWPFParagraph pTitle = doc.CreateParagraph();
            pTitle.Alignment = ParagraphAlignment.CENTER;
            pTitle.VerticalAlignment = TextAlignment.CENTER;
            pTitle.SpacingBefore = 300;
            pTitle.SpacingAfter = 300;
            XWPFRun rTitle = pTitle.CreateRun();
            string weekName = DigitToChnHelper.Convert(indexWeek.ToString(), false);
            rTitle.SetText(string.Format("第{0}周: {1}~{2}", weekName, startDate.ToString("yyyy-MM-dd"),
                endDate.ToString("yyyy-MM-dd")));
            rTitle.IsBold = true;
            rTitle.FontFamily = "微软雅黑";
            rTitle.FontSize = 20;
            indexWeek++;
            // 大序号一 项目列表
            XWPFParagraph pPara1 = doc.CreateParagraph();
            pPara1.Alignment = ParagraphAlignment.LEFT;
            pPara1.VerticalAlignment = TextAlignment.AUTO;
            pPara1.SpacingBefore = 300;
            pPara1.SpacingAfter = 300;
            XWPFRun rPara1 = pPara1.CreateRun();
            rPara1.SetText("一、项目列表");
            rPara1.IsBold = true;
            rPara1.FontFamily = "微软雅黑";
            rPara1.FontSize = 12;
            // 表格
            XWPFTable table = doc.CreateTable();
            table.RemoveRow(0);
            //  -  标题行
            XWPFTableRow row0 = DocxHelper.CreateRow(table);
            XWPFTableCell cel00 = DocxHelper.CreateCell(row0);
            cel00.SetText("序号");
            XWPFTableCell cel01 = DocxHelper.CreateCell(row0);
            cel01.SetText("名称");
            XWPFTableCell cel02 = DocxHelper.CreateCell(row0);
            cel02.SetText("工时");
            XWPFTableCell cel03 = DocxHelper.CreateCell(row0);
            cel03.SetText("加班");
            //  -  数据行
            for (int i = 0; i < count; i++)
            {
                var detail = list[i];
                XWPFTableRow row = DocxHelper.CreateRow(table);
                XWPFTableCell cel0 = DocxHelper.CreateCell(row);
                cel0.SetText((i + 1).ToString());
                XWPFTableCell cel1 = DocxHelper.CreateCell(row);
                cel1.SetText(detail.Name);
                XWPFTableCell cel2 = DocxHelper.CreateCell(row);
                cel2.SetText(detail.WorkHour.ToString("N1"));
                XWPFTableCell cel3 = DocxHelper.CreateCell(row);
                cel3.SetText(detail.Overtime.ToString("N1"));
            }
            // 大序号二 工作简介
            XWPFParagraph pPara2 = doc.CreateParagraph();
            pPara2.Alignment = ParagraphAlignment.LEFT;
            pPara2.VerticalAlignment = TextAlignment.AUTO;
            pPara2.SpacingBefore = 300;
            pPara2.SpacingAfter = 300;
            XWPFRun rPara2 = pPara2.CreateRun();
            rPara2.SetText("二、项目简介");
            rPara2.IsBold = true;
            rPara2.FontFamily = "微软雅黑";
            rPara2.FontSize = 12;
            // 循环 - 小序号简介
            XWPFParagraph pInfo = doc.CreateParagraph();
            pInfo.Alignment = ParagraphAlignment.LEFT;
            pInfo.VerticalAlignment = TextAlignment.AUTO;
            pInfo.SpacingBefore = 200;
            pInfo.SpacingAfter = 200;
            for (int i = 0; i < count; i++)
            {
                var detail = list[i];
                XWPFRun rName = pInfo.CreateRun();
                rName.SetText(string.Format("{0}. {1}:", (i + 1), detail.Name));
                rName.IsBold = true;
                rName.FontFamily = "微软雅黑";
                rName.FontSize = 9;
                rName.AddCarriageReturn();

                int countText = detail.Count;
                for (int j = 0; j < countText; j++)
                {
                    XWPFRun rDetail = pInfo.CreateRun();
                    string text = detail.TextList[j];
                    if (!string.IsNullOrWhiteSpace(detail.RemarkList[j]))
                        text += " - " + detail.RemarkList[j];
                    rDetail.SetText(text);
                    rDetail.IsBold = false;
                    rDetail.FontFamily = "微软雅黑";
                    rDetail.FontSize = 9;
                    rDetail.AddCarriageReturn();
                }
            }
            // 大序号三 总结
            if (summarize)
            {
                XWPFParagraph pPara3 = doc.CreateParagraph();
                pPara3.Alignment = ParagraphAlignment.LEFT;
                pPara3.VerticalAlignment = TextAlignment.AUTO;
                pPara3.SpacingBefore = 300;
                pPara3.SpacingAfter = 300;
                XWPFRun rPara3 = pPara3.CreateRun();
                rPara3.SetText("三、总结");
                rPara3.IsBold = true;
                rPara3.FontFamily = "微软雅黑";
                rPara3.FontSize = 12;
            }
            return true;
        }

        public static bool WriteDocxWeekPlan(ref XWPFDocument doc, List<string> listWeekPlan)
        {
            // 插入分页符
            if (indexWeek != 1)
            {
                XWPFParagraph pBreak = doc.CreateParagraph();
                XWPFRun rBreak = pBreak.CreateRun();
                rBreak.AddBreak();
            }
            // 标题
            XWPFParagraph pTitle = doc.CreateParagraph();
            pTitle.Alignment = ParagraphAlignment.CENTER;
            pTitle.VerticalAlignment = TextAlignment.CENTER;
            pTitle.SpacingBefore = 300;
            pTitle.SpacingAfter = 300;
            XWPFRun rTitle = pTitle.CreateRun();
            rTitle.SetText("下周工作计划列表");
            rTitle.IsBold = true;
            rTitle.FontFamily = "微软雅黑";
            rTitle.FontSize = 20;
            // 表格
            XWPFTable table = doc.CreateTable();
            table.RemoveRow(0);
            //  -  标题行
            int count = listWeekPlan.Count;
            XWPFTableRow row0 = DocxHelper.CreateRow(table);
            XWPFTableCell cel00 = DocxHelper.CreateCell(row0);
            cel00.SetText("序号");
            XWPFTableCell cel01 = DocxHelper.CreateCell(row0);
            cel01.SetText("名称");
            //  -  数据行
            for (int i = 0; i < count; i++)
            {
                XWPFTableRow row = DocxHelper.CreateRow(table);
                XWPFTableCell cel0 = DocxHelper.CreateCell(row);
                cel0.SetText((i + 1).ToString());
                XWPFTableCell cel1 = DocxHelper.CreateCell(row);
                cel1.SetText(listWeekPlan[i]);
            }

            return true;
        }

        public static bool WriteDocx(string userName, DataTable dt, DateTime startDate, DateTime endDate,
            string fileName, List<string> listWeekPlan, bool summarize = false)
        {
            //简单的输入判断
            if (userName == null || dt == null | string.IsNullOrEmpty(fileName)) return false;
            if (startDate > endDate)
            {
                DateTime dateTmp = startDate;
                startDate = endDate;
                endDate = dateTmp;
            }
            startDate = new DateTime(startDate.Year, startDate.Month, startDate.Day);
            endDate = new DateTime(endDate.Year, endDate.Month, endDate.Day);
            endDate = endDate.AddDays(1);   // 用户输入日期原意应为包含所选的最后一天
            // 创建文件类
            XWPFDocument doc = new XWPFDocument();
            // 文件总标题
            XWPFParagraph pContent = doc.CreateParagraph();
            pContent.Alignment = ParagraphAlignment.CENTER;
            pContent.VerticalAlignment = TextAlignment.CENTER;
            pContent.SpacingBefore = 200;
            pContent.SpacingAfter = 200;
            XWPFRun rContent = pContent.CreateRun();
            rContent.SetText("周工作总结 - " + userName);
            rContent.IsBold = true;
            rContent.FontFamily = "隶书";
            rContent.FontSize = 28;
            rContent.SetColor("#0066CC"); // 海蓝色
            // 日期范围
            XWPFParagraph pDate = doc.CreateParagraph();
            pDate.Alignment = ParagraphAlignment.RIGHT;
            pDate.VerticalAlignment = TextAlignment.CENTER;
            pDate.SpacingAfter = 600;
            XWPFRun rDate = pDate.CreateRun();
            rDate.SetText(string.Format("记录范围：{0} ~ {1}", startDate.ToString("yyyy-MM-dd"),
                endDate.ToString("yyyy-MM-dd")));
            rDate.IsBold = false;
            rDate.FontFamily = "微软雅黑";
            rDate.FontSize = 9;
            rDate.AddCarriageReturn();
            // 写入每周数据
            indexWeek = 1;
            var listDate = GetWeekList(startDate, endDate);
            foreach (DateRange dr in listDate)
            {
                WriteDocxWeek(ref doc, dt, dr.StartDate, dr.EndDate, summarize);
            }
            // 写入下周计划
            if (listWeekPlan != null && listWeekPlan.Count > 0)
            {
                WriteDocxWeekPlan(ref doc, listWeekPlan);
            }
            // 输出
            if (!fileName.EndsWith(".docx")) fileName += ".docx";
            try
            {
                using (FileStream fs = new FileStream(fileName, FileMode.Create))
                {
                    doc.Write(fs);
                    fs.Close();
                }
            }
            catch (Exception e)
            {
                LogHelper.WriteLog(nameof(WriteDocx), e, fileName);
                return false;
            }
            return true;
        }

        private static List<DateRange> GetWeekList(DateTime startDate, DateTime endDate)
        {
            List<DateRange> list = new List<DateRange>();

            if (endDate == startDate)
            {
                list.Add(new DateRange(startDate, endDate));
                return list;
            }

            if ((endDate - startDate < new TimeSpan(7, 0, 0, 0)) && GetWeekNo(startDate) < GetWeekNo(endDate))
            {
                list.Add(new DateRange(startDate, endDate));
                return list;
            }

            int weeknoEnd = GetWeekNo(endDate);
            var endMid = endDate.AddDays(-weeknoEnd);
            list.Add(new DateRange(endMid, endDate));
            endMid = endMid.AddDays(-1);
            while (startDate <= endMid)
            {
                if (startDate == endMid)
                {
                    list.Add(new DateRange(startDate, startDate));
                    break;
                }

                var startMid = endMid.AddDays(-6);
                if (startMid < startDate) startMid = startDate;
                list.Add(new DateRange(startMid, endMid));
                endMid = startMid.AddDays(-1);
            }
            list.Reverse();
            return list;
        }

        private static int GetWeekNo(DateTime date)
        {
            int val = -1;
            var w = date.DayOfWeek;
            switch (w)
            {
                case DayOfWeek.Sunday:
                    val = 0;
                    break;
                case DayOfWeek.Monday:
                    val = 1;
                    break;
                case DayOfWeek.Tuesday:
                    val = 2;
                    break;
                case DayOfWeek.Wednesday:
                    val = 3;
                    break;
                case DayOfWeek.Thursday:
                    val = 4;
                    break;
                case DayOfWeek.Friday:
                    val = 5;
                    break;
                case DayOfWeek.Saturday:
                    val = 6;
                    break;
            }
            return val;
        }
    }

    

    public class DateRange
    {
        public DateTime StartDate { get; set; }
        public DateTime EndDate { get; set; }

        public DateRange(DateTime startDate, DateTime endDate)
        {
            StartDate = startDate;
            EndDate = endDate;
        }
    }

    public class ProjectDetail
    {
        public string Name { get; set; }
        public double WorkHour { get; set; }
        public double Overtime { get; set; }
        public List<string> TextList { get; set; }
        public List<string> RemarkList { get; set; }

        public int Count => TextList.Count;

        public ProjectDetail(string name)
        {
            Name = name;
            WorkHour = 0;
            Overtime = 0;
            TextList = new List<string>();
            RemarkList = new List<string>();
        }
    }
}